﻿using log4net;
using Newtonsoft.Json.Linq;
using per.esmool.utils;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace FlowSimulate {

    /// <summary>
    /// 使用方法参见 https://developer.baidu.com/article/detail.html?id=1089328
    /// 其中 AIClientID 和 AIClientSecret 参见 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5#header%E5%8F%82%E6%95%B0
    /// </summary>
    public class AIRequester {

        private static readonly ILog LOG = LogManager.GetLogger(typeof(AIRequester));

        /// <summary>
        /// 参见 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5#header%E5%8F%82%E6%95%B0
        /// </summary>
        public string AIClientID { get; set; }

        /// <summary>
        /// 参见 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5#header%E5%8F%82%E6%95%B0
        /// </summary>
        public string AIClientSecret { get; set; }

        /// <summary>
        /// 参考: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5
        /// </summary>
        public string RequestAccessToken() {
            var url = @"https://aip.baidubce.com/oauth/2.0/token";
            var data = new JObject {
                { "grant_type"   , "client_credentials" },
                { "client_id"    , this.AIClientID      },
                { "client_secret", this.AIClientSecret  },
            };
            var task = PostJson(url, data);
            task.RunSynchronously();
            var response = task.Result ?? throw new IOException($"Failed request server to get access token");

            var error = JsonKit.GetValue<string>(response, "error", null);
            if (error is not null)
                throw new IOException($"Failed to acquire access_token, error={error}");

            var accessToken = response.Value<string>("access_token");
            return accessToken;
        }

        /// <summary>
        /// 参考: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11
        /// </summary>
        public static string ERNIEBot(string accessToken, string prompt) {
            var url = @"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions";
            var data = new JObject {
                { "access_token", accessToken },
                { "messages", new JArray {
                    new JObject {
                        { "role", "user" },
                        { "content", prompt },
                    }
                }},
                { "response_format", "json_object" }
            };
            var task = PostJson(url, data);
            task.RunSynchronously();
            var response = task.Result ?? throw new IOException("Failed to request server to chat");
            var flag = response.Value<int>("flag");
            if (flag != 0)
                throw new IOException($"Failed to invoke ERNIEBot, flag={flag}");

            var result = response.Value<string>("result");
            return result;
        }

        private static async Task<JObject> PostJson(string url, JObject data) {
            try {
                JsonContent content = JsonContent.Create(data, typeof(JObject));
                using HttpClient client = new();
                var response = await client.PostAsync(url, content);
                var text = await response.Content.ReadAsStringAsync();
                return JObject.Parse(text);
            } catch (Exception err) {
                LOG.Warn($"Failed request from {url}", err);
                return new JObject {
                    { "error", err.Message },
                    { "flag", -1 }
                };
            }
        }
    }
}
